import { defineComponent, onMounted, onUnmounted, ref, watch } from 'vue';
import { useNamespace } from '@ibiz-template/vue3-util';
import { showTitle } from '@ibiz-template/core';
import { IUIEvent, calendarWeekEmits, calendarWeekProps } from '../interface';
import { useCalendarWeek } from './use-calendar-week';
import './calendar-week.scss';
import { closeIcon, handlePopClose } from '../util';

export const CalendarWeek = defineComponent({
  name: 'CalendarWeek',
  props: calendarWeekProps,
  emits: calendarWeekEmits,
  setup(props, { emit, slots }) {
    const ns = useNamespace('calendar-week');
    const {
      drawData,
      resizableHand,
      rows,
      weekDays,
      curTimeTimer,
      calendarWeek,
      selectedData,
      legends,
      rowsHeader,
      eventClick,
      handleDrag,
      handleDragStart,
      handleCurTime,
      initDrawData,
      handleUIEvents,
    } = useCalendarWeek(props, emit);

    // 当前悬浮项
    const hoverItem = ref('');

    // 控制项popover显示
    const visible = ref(false);

    watch(
      () => props.selectedData,
      () => {
        if (props.selectedData && props.selectedData.length > 0) {
          const data =
            props.selectedData.length > selectedData.value.length
              ? props.selectedData
              : selectedData.value;
          selectedData.value = data;
        } else {
          selectedData.value = [];
        }
      },
      { immediate: true, deep: true },
    );

    watch(
      () => props.legends,
      () => {
        legends.value = props.legends || [];
        handleUIEvents();
      },
      { immediate: true, deep: true },
    );

    watch(
      () => props.events,
      () => {
        handleUIEvents();
      },
      { immediate: true, deep: true },
    );

    onMounted(() => {
      handleCurTime();
      drawData.value = initDrawData();
      curTimeTimer.value = setInterval(() => handleCurTime(), 1000);
    });

    onUnmounted(() => {
      const timer = curTimeTimer.value;
      if (timer) {
        clearInterval(timer);
        curTimeTimer.value = null;
      }
    });

    /**
     * 显示popover
     *
     * @param {IUIEvent} event
     */
    const onMouseenter = (event: IUIEvent) => {
      hoverItem.value = String(event.id);
      visible.value = true;
    };

    // 项点击
    const onClickCalendarItem = () => {
      visible.value = false;
    };

    /**
     * 隐藏popover
     *
     */
    const onMouseleavee = () => {
      hoverItem.value = '';
      visible.value = false;
    };

    /**
     * 绘制事件项
     * @param {string} location 绘制位置
     * @param {IParams} eventBoxStyle 事件容器中style样式
     * @param {IParams} eventContentStyle 事件内容区中style样式
     * @param {IUIEvent} event 事件项数据
     * @param {number} index 事件项下标
     * @param {string} slotNme 事件项插槽名字
     * @param {string} classEName 事件项绘制类名
     */
    const renderEventItem = (
      location: string,
      eventBoxStyle: IParams,
      eventContentStyle: IParams,
      event: IUIEvent,
      index: number,
      slotNme: string,
      classEName: string,
    ) => {
      return (
        <div
          key={index}
          class={[ns.em(classEName, 'event-box')]}
          style={eventBoxStyle}
          onMouseenter={() => onMouseenter(event)}
          onMouseleave={onMouseleavee}
          onClick={onClickCalendarItem}
        >
          <button
            class={[
              ns.em(classEName, 'event-content'),
              event.isSelectedEvent ? 'is-selected-event' : '',
              event.classname,
            ]}
            onClick={() => {
              eventClick(event, 'head');
            }}
            style={eventContentStyle}
          >
            {slots[slotNme] ? (
              slots[slotNme]?.({ data: event })
            ) : (
              <div
                class={[ns.em(classEName, 'event-summary'), event.classname]}
                title={showTitle(
                  location === 'header'
                    ? `${event.text || ''} ${event.timeRange || ''}`
                    : '',
                )}
              >
                {event.icon && (
                  <span
                    class={[event.icon, ns.em(classEName, 'event-icon')]}
                    style={{
                      color: event.bkColor,
                    }}
                  ></span>
                )}
                {event.text && (
                  <span class={[ns.em(classEName, 'event-name')]}>
                    {event.text}
                  </span>
                )}
              </div>
            )}
            {location === 'header' && event.isSelectedEvent ? (
              <span class={['fa fa-check', ns.em(classEName, 'check')]}></span>
            ) : (
              ''
            )}
          </button>
        </div>
      );
    };

    /**
     * 绘制事件项popover
     * @param {Element} content 内容
     * @param {IUIEvent} event 事件项
     */
    const renderPopover = (content: Element, event: IUIEvent) => {
      if (!props.showDetail) {
        return content;
      }
      return (
        <el-popover
          visible={visible.value && event.id === hoverItem.value}
          show-after={100}
          offset={4}
          width='auto'
          popper-class={[ns.e('event-popover')]}
          placement='right-start'
        >
          {{
            reference: () => content,
            default: () => {
              return (
                <div class={[ns.em('event-popover', 'body')]}>
                  <div
                    class={[ns.em('event-popover', 'close')]}
                    onClick={el => handlePopClose(el)}
                    v-html={closeIcon}
                  ></div>
                  <div class={[ns.em('event-popover', 'scroll')]}>
                    {slots?.event ? (
                      slots.event?.({ data: event })
                    ) : (
                      <div class={[ns.em('event-popover', 'content')]}>{`${
                        event.text || ''
                      } ${event.timeRange || ''}`}</div>
                    )}
                  </div>
                </div>
              );
            },
          }}
        </el-popover>
      );
    };

    /**
     * 绘制头部
     */
    const renderHeader = () => {
      return (
        <div
          class={[ns.e('header')]}
          ref={el => {
            resizableHand.value = el;
          }}
        >
          <div class={[ns.em('header', 'dates')]}>
            <div class={[ns.em('header', 'date-cell-first')]}></div>
            {weekDays.value.map((weekDay: IParams) => (
              <div class={[ns.em('header', 'date-cell')]}>
                <div class={[ns.em('header', 'date-week')]}>
                  {weekDay.caption}
                </div>
                <div
                  class={[
                    ns.em('header', 'date-day'),
                    weekDay.isActivate ? 'is-today' : '',
                  ]}
                >
                  {weekDay.day}
                </div>
              </div>
            ))}
          </div>
          <div class={[ns.em('header', 'events')]}>
            <div class={[ns.em('header', 'event-cell-first')]}>
              {ibiz.i18n.t('control.calendar.calendardaily.tip')}
            </div>
            {rowsHeader.value.map((item: IData) => (
              <div class={[ns.em('header', 'event-cell')]}>
                {item.map((event: IUIEvent, index: number) => {
                  const eventBoxStyle = {
                    top: `${Number(index * 26) + 2}px`,
                    left: `${event.styleLeft}`,
                    width: `${event?.width}`,
                  };
                  const eventContentStyle = {
                    color: event.color,
                    background: event.bkColorFade,
                  };
                  return event.isShow
                    ? renderEventItem(
                        'header',
                        eventBoxStyle,
                        eventContentStyle,
                        event,
                        index,
                        'head-event',
                        'header',
                      )
                    : '';
                })}
              </div>
            ))}
          </div>
          <div
            class={ns.em('header', 'resizable-handle')}
            draggable='true'
            onDrag={(event: DragEvent) => handleDrag(event)}
            onDragstart={(event: DragEvent) => handleDragStart(event)}
          >
            <div class={ns.em('header', 'resize-line')}></div>
          </div>
        </div>
      );
    };

    /**
     * 绘制内容区
     */
    const renderContent = () => {
      return (
        <div class={[ns.e('scroll-area')]}>
          <div class={ns.e('time-pane')}>
            <div class={ns.em('time-pane', 'time-labels')}>
              {drawData.value.map((timescale: string) => (
                <div key={timescale} class={[ns.em('time-pane', 'time-label')]}>
                  {timescale}
                </div>
              ))}
            </div>
            {rows.value.map((item: IData) => (
              <div class={ns.em('time-pane', 'time-columns')}>
                {drawData.value.map((timescale: string, index: number) => (
                  <div
                    key={timescale}
                    class={[
                      ns.em('time-pane', 'time-column'),
                      index === drawData.value.length - 1 &&
                        ns.em('time-pane', 'time-column-last'),
                    ]}
                  ></div>
                ))}

                <div class={ns.em('time-pane', 'event-timed-container')}>
                  <div class={ns.em('time-pane', 'container-scroll')}>
                    {item.map((event: IUIEvent, index: number) => {
                      const eventBoxStyle = {
                        top: `${event.styleTop}px`,
                        left: `${event.styleLeft}`,
                        height: `${event.height}px`,
                        width: `${event.width}`,
                        'min-height': `${event.height}px`,
                        'z-index': event.zIndex,
                      };
                      const eventContentStyle = {
                        background: event.bkColorFade,
                        'border-left': `3px solid ${event.bkColor}`,
                        color: event.color,
                      };
                      const tempContent = renderEventItem(
                        'content',
                        eventBoxStyle,
                        eventContentStyle,
                        event,
                        index,
                        '',
                        'time-pane',
                      );
                      return renderPopover(
                        tempContent as unknown as Element,
                        event,
                      );
                    })}
                  </div>
                </div>
              </div>
            ))}
          </div>
        </div>
      );
    };
    return {
      ns,
      calendarWeek,
      renderHeader,
      renderContent,
    };
  },
  render() {
    return (
      <div
        ref={el => {
          this.calendarWeek = el;
        }}
        class={this.ns.b()}
      >
        {this.renderHeader()}
        {this.renderContent()}
      </div>
    );
  },
});
